﻿#include "ThreadAlloc.h"
#include "Common.h"
#include <cstdio>  // For proper printf

// ntimes 一轮申请和释放内存的次数
// nworks 线程个数
// rounds 轮次
void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
    std::vector<std::thread> vthread(nworks);
    size_t malloc_costtime = 0;
    size_t free_costtime = 0;
    std::mutex costtime_mutex;

    for (size_t k = 0; k < nworks; ++k)
    {
        vthread[k] = std::thread([&, k]() {
            std::vector<void*> v;
            v.reserve(ntimes);

            for (size_t j = 0; j < rounds; ++j)
            {
                size_t begin1 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    v.push_back(malloc(16));
                    //v.push_back(malloc((16 + i) % 8192 + 1));
                }
                size_t end1 = clock();

                size_t begin2 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    free(v[i]);
                }
                size_t end2 = clock();
                v.clear();

                {
                    std::lock_guard<std::mutex> lock(costtime_mutex);
                    malloc_costtime += (end1 - begin1);
                    free_costtime += (end2 - begin2);
                }
            }
            });
    }

    for (auto& t : vthread)
    {
        t.join();
    }

    printf("%zu个线程并发执行%zu轮次，每轮次malloc %zu次: 花费：%zu ms\n",
        nworks, rounds, ntimes, malloc_costtime);

    printf("%zu个线程并发执行%zu轮次，每轮次free %zu次: 花费：%zu ms\n",
        nworks, rounds, ntimes, free_costtime);

    printf("%zu个线程并发malloc&free %zu次，总计花费：%zu ms\n",
        nworks, nworks * rounds * ntimes, malloc_costtime + free_costtime);
}

// 单轮次申请释放次数 线程数 轮次
void BenchmarkThreadMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
    std::vector<std::thread> vthread(nworks);
    size_t malloc_costtime = 0;
    size_t free_costtime = 0;
    std::mutex costtime_mutex;

    for (size_t k = 0; k < nworks; ++k)
    {
        vthread[k] = std::thread([&]() {
            std::vector<void*> v;
            v.reserve(ntimes);

            for (size_t j = 0; j < rounds; ++j)
            {
                size_t begin1 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    v.push_back(ThreadAlloc(16));
                    //v.push_back(ThreadAlloc((16 + i) % 8192 + 1));
                }
                size_t end1 = clock();

                size_t begin2 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    ThreadDeAlloc(v[i]);
                }
                size_t end2 = clock();
                v.clear();

                {
                    std::lock_guard<std::mutex> lock(costtime_mutex);
                    malloc_costtime += (end1 - begin1);
                    free_costtime += (end2 - begin2);
                }
                //std::cout << "一轮结束，准备开始下一轮" << std::endl;
                //Sleep(3000);
            }
            });
    }

    for (auto& t : vthread)
    {
        t.join();
    }

    printf("%zu个线程并发执行%zu轮次，每轮次concurrent alloc %zu次: 花费：%zu ms\n",
        nworks, rounds, ntimes, malloc_costtime);

    printf("%zu个线程并发执行%zu轮次，每轮次concurrent dealloc %zu次: 花费：%zu ms\n",
        nworks, rounds, ntimes, free_costtime);

    printf("%zu个线程并发concurrent alloc&dealloc %zu次，总计花费：%zu ms\n",
        nworks, nworks * rounds * ntimes, malloc_costtime + free_costtime);
}

int main()
{
    //size_t n = 100000;
    size_t n = 10000;
    cout << "==========================================================" << endl;
    BenchmarkThreadMalloc(n, 4, 10);
    cout << endl << endl;
    BenchmarkMalloc(n, 4, 10);
    cout << "==========================================================" << endl;

    return 0;
}